package com.atguigu.gmall.list.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.atguigu.gmall.list.model.Goods;
import com.atguigu.gmall.list.model.SearchAttr;
import com.atguigu.gmall.list.service.SearchService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.product.model.BaseAttrInfo;
import com.atguigu.gmall.product.model.BaseCategoryView;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.atguigu.gmall.product.model.SkuInfo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings("all")
public class SearchServiceImpl implements SearchService {

    //注入远程调用fen注解
    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public static final String index_name = "goods";

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;


    @Autowired
    private SearchService searchService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 测试接口，商品文档对象录入索引
     *
     * @param skuId
     * @return
     */
    @Override
    public void upperGoods(Long skuId) {
        try {
            //1创建索引文档对象goods
            Goods goods = new Goods();
            goods.setId(skuId);
            //2通过远程fen调用  -根据商品的skuid查询商品的基本信息
            //创建线程池 skuInfoCompletableFuture
            CompletableFuture<SkuInfo> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
                SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
                if (skuInfo != null) {
                    goods.setCategory3Id(skuInfo.getCategory3Id());
                    goods.setDefaultImg(skuInfo.getSkuDefaultImg());
                    goods.setTitle(skuInfo.getSkuName());
                    goods.setTmId(skuInfo.getTmId());
                }
                return skuInfo;
            }, threadPoolExecutor);

            //获取商品价格
            BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);
            if (skuPrice != null) {
                //转换Double
                goods.setPrice(skuPrice.doubleValue());
            }

            //3.远程调用商品微服务-根据分类ID查询分类信息.
            CompletableFuture<Void> categoryCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
                BaseCategoryView categoryView = productFeignClient.getCategoryView(skuInfo.getCategory3Id());
                if (categoryView != null) {
                    goods.setCategory1Id(categoryView.getCategory1Id());
                    goods.setCategory1Name(categoryView.getCategory1Name());

                    goods.setCategory2Id(categoryView.getCategory2Id());
                    goods.setCategory2Name(categoryView.getCategory2Name());

                    goods.setCategory3Id(categoryView.getCategory3Id());
                    goods.setCategory3Name(categoryView.getCategory3Name());
                }

            }, threadPoolExecutor);

            //4.远程调用商品微服务-根据品牌ID查询品牌信息
            CompletableFuture<Void> priceCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
                BaseTrademark trademark = productFeignClient.getTrademark(skuInfo.getTmId());
                if (trademark != null) {
                    goods.setTmId(trademark.getId());
                    goods.setTmName(trademark.getTmName());
                    goods.setTmLogoUrl(trademark.getLogoUrl());
                }
            }, threadPoolExecutor);

            //5.远程调用商品微服务-根据skuID查询平台属性列表
            CompletableFuture<Void> attrInfoCompletableFuture = CompletableFuture.runAsync(() -> {
                List<BaseAttrInfo> attrList = productFeignClient.getAttrList(skuId);
                if (!CollectionUtils.isEmpty(attrList)) {
                    List<SearchAttr> searchAttrList = attrList.stream().map(baseAttrInfo -> {
                        SearchAttr searchAttr = new SearchAttr();
                        searchAttr.setAttrId(baseAttrInfo.getId());
                        searchAttr.setAttrName(baseAttrInfo.getAttrName());
                        searchAttr.setAttrValue(baseAttrInfo.getAttrValue());
                        return searchAttr;
                    }).collect(Collectors.toList());
                    goods.setAttrs(searchAttrList);
                }
            }, threadPoolExecutor);

            goods.setCreateTime(new Date());
            goods.setCreatedDate(new Date());

            //全部执行
            CompletableFuture.allOf(
                    skuInfoCompletableFuture,
                    priceCompletableFuture,
                    attrInfoCompletableFuture,
                    categoryCompletableFuture).join();


            //6.调用JavaHighLevelRestClient完成文档新增  本质上发起http请求
            //6.1 构建创建文档请求对象 IndexReqeust  封装新增数据对应索引库库名称  文档ID
            IndexRequest request = new IndexRequest(index_name).id(skuId.toString());

            //6.2 构建新增文档请求体参数  JSON
            request.source(JSON.toJSONString(goods), XContentType.JSON);
            //6.3 发起请求 请求ES
            restHighLevelClient.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("[搜索服务]上架商品:{},失败原因:{}", skuId, e);
            throw new RuntimeException(e);
        }
    }


    /**
     * 将指定商品从索引库删除
     *
     * @param skuId
     */
    @Override
    public void lowerGoods(Long skuId) {
        try {
            DeleteRequest request = new DeleteRequest(index_name, skuId.toString());
            restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("[搜索服务]下架商品:{},失败原因:{}", skuId, e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 提供给详情服务调用:更新商品热度分值
     *
     * @param skuId
     */

    @Override
    public void incrHotScore(Long skuId) {
        try {
            // 1.更新Redis缓冲中商品分值
            String key = "hotScore";
            Double skuHotScore = redisTemplate.opsForZSet().incrementScore(key, skuId.toString(), 1);
            // 2.更新ES文档中商品分值(稀释写操作)
            if (skuHotScore % 10 == 0) {
                //2.1 创建更新文档请求对象 文档ID 文档分值
                UpdateRequest updateRequest = new UpdateRequest(index_name, skuId.toString());
                Goods goods = new Goods();
                goods.setHotScore(skuHotScore.longValue());
                updateRequest.doc(JSON.toJSONString(goods), XContentType.JSON);
                restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            }
        } catch (IOException e) {
            log.error("[搜索微服务]更新商品分值:{},异常信息:{}", skuId, e);
            throw new RuntimeException(e);
        }
    }


}
